#ifndef _UI_HPP
#define _UI_HPP

bool pageCurrent(int pageNum);
void uiInitTask();
void pageShow(int pageNum);

lv_obj_t *root;
lv_obj_t *pageMain;
lv_obj_t *pageInfo;
lv_obj_t *pageHome;
lv_obj_t *pageSettings;

lv_disp_t *disp;


typedef struct pageItem{
	lv_obj_t *pageObj;
	char *name;
	bool show;
	void (*pageShowFun)();
} page_t;

page_t pages[PAGE_CNT];
static int lastPage = 0;

#include CFONT_FILE
#include "common/ui_color.h"
#include "module/ui_keyborad.h"
#include "module/ui_top_status_bar.h"
#include "module/ui_note.h"
#include "module/ui_qrcode.h"
#include "pages/page_home.h"
#include "pages/page_info.h"
#include "pages/page_settings.h"
#include "pages/page_init.h"

#define LV_TICK_PERIOD_MS 1
#define LV_TIMER_DELAY 10


void pageReturn() {
	log("page return, last page = %d", lastPage);
	pageShow(lastPage);
}

void pageShow(int pageNum) {
	for(int i = 0; i < PAGE_CNT; i++) {
		if(i != pageNum && pages[i].show) {
			lastPage = i;
			pages[i].show = false;
			LVMT;
			lv_obj_add_flag(pages[i].pageObj, LV_OBJ_FLAG_HIDDEN);
			LVMG;
		}
	}
	pages[pageNum].show = true;
	// if(!pages[pageNum].initDone) {
	// 	pages[pageNum].initFun();
	// 	pages[pageNum].initDone = true;
	// }
	pages[pageNum].pageShowFun();
	LVMT;
	lv_obj_clear_flag(pages[pageNum].pageObj, LV_OBJ_FLAG_HIDDEN);
	lv_obj_move_foreground(pages[pageNum].pageObj);
	LVMG;

}

bool pageCurrent(int pageNum) {
	return pages[pageNum].show;
}

static bool xpt2046Read(lv_indev_drv_t * drv, lv_indev_data_t * data) {
    static int16_t last_x = 0;
    static int16_t last_y = 0;
    bool valid = false;

    int16_t x = last_x;
    int16_t y = last_y;
    if (xpt2048_is_touch_detected() == TOUCH_DETECTED) {
        valid = true;

        x = xpt2046_cmd(CMD_X_READ);
        y = xpt2046_cmd(CMD_Y_READ);

        x = x >> 4;
        y = y >> 4;
        
        xpt2046_corr(&x, &y);
        xpt2046_avg(&x, &y);
        last_x = x;
        last_y = y;
    }
    else {
        avg_last = 0;
    }

    data->point.x = x;
    data->point.y = y;
    data->state = valid == false ? LV_INDEV_STATE_REL : LV_INDEV_STATE_PR;

    return false;
}

static void touchDriverRead(lv_indev_drv_t *drv, lv_indev_data_t *data) {
	bool res = false;
	res = xpt2046Read(drv, data);
	data->continue_reading = res;
}


static void lvTickTask() {
	lv_tick_inc(LV_TICK_PERIOD_MS);
}

void uiInitTask() {
	
	lv_init();
	lvgl_driver_init();
	// 320 * 40
	lv_color_t *lvglBuf_1 = heap_caps_malloc(DISP_BUF_SIZE * sizeof(lv_color_t), MALLOC_CAP_DMA);
	assert(lvglBuf_1 != NULL);
	lv_color_t *lvglBuf_2 = heap_caps_malloc(DISP_BUF_SIZE * sizeof(lv_color_t), MALLOC_CAP_DMA);
	assert(lvglBuf_2 != NULL);

	static lv_disp_draw_buf_t dispBuf;
	uint32_t size_in_px = DISP_BUF_SIZE;

	lv_disp_draw_buf_init(&dispBuf, lvglBuf_1, lvglBuf_2, size_in_px);
	lv_disp_drv_t dispDrv;
	lv_disp_drv_init(&dispDrv);
	dispDrv.flush_cb = disp_driver_flush;
	dispDrv.draw_buf = &dispBuf;
	dispDrv.hor_res = LV_HOR_RES_MAX;
	dispDrv.ver_res = LV_VER_RES_MAX;
	disp = lv_disp_drv_register(&dispDrv);

	// 触摸
	lv_indev_drv_t indevDrv;
    lv_indev_drv_init(&indevDrv);
	indevDrv.type = LV_INDEV_TYPE_POINTER;
    indevDrv.read_cb = touchDriverRead;
    lv_indev_drv_register(&indevDrv);


	const esp_timer_create_args_t periodic_timer_args = {
		.callback = &lvTickTask,
		.name = "periodicGui",
	};
	esp_timer_handle_t periodic_timer;
	err = esp_timer_create(&periodic_timer_args, &periodic_timer);
	if(err != ESP_OK) {
		log("timer create err = %d", err);
	}
	
	err = esp_timer_start_periodic(periodic_timer, LV_TICK_PERIOD_MS * 1000);
	if(err != ESP_OK) {
		log("start perioddic err = %d", err);
	}

	xEventGroupSetBits(eventGroup, EVENT_SCREEN_INIT_DONE);
	
	while (1) {
		LVMT;
		lv_timer_handler();
		LVMG;
		DELAY(LV_TIMER_DELAY);
	}

	free(lvglBuf_1);
	free(lvglBuf_2);

	vTaskDelete(NULL);    
}

#endif